using System;
using System.Collections.Generic;
using MoonFramework.Scripts.Pool;
using MoonFramework.Scripts.Tool;

namespace MoonFramework.FSM
{
    public class BaseFsm<T>
    {
        public Dictionary<string, IState> fsmStates;   //集合
        public Dictionary<string, HashSet<string>> transitionMap; // 状态过渡字典

        public string curState;
        public T entity;

        public virtual void Init(string curState, T entity) 
        {
            fsmStates = new();
            transitionMap = new();

            this.curState = curState;            
            this.entity = entity;
        }
        
        public IState AllocateState<T>(string name,Func<T> fun,Action<T> callback = null) where T : class, IState
        {
            IState state = this.MoonObjGetPool(fun);
            AddState(name, state);
            callback?.Invoke((T)state);
            return (T)state;
        }
        
        public void AddState(string name, IState state)
            => fsmStates?.Add(name, state);

        public void RemoveState(string name)
        {
            if(!fsmStates.TryGetValue(name, out var state))
                return;
            ObjPoolManager.Instance.Push(state);
            fsmStates?.Remove(name);
        }

        public void AddTransition(string from, string to)
        {
            if (!transitionMap.ContainsKey(from))
                transitionMap.Add(from, new HashSet<string>());
            transitionMap[from].Add(to);
        }

        public virtual void ChangeState(string type, bool isForce = false)
        {
            if (!isForce && (type == curState ||
                !fsmStates.ContainsKey(type) ||
               !transitionMap[curState].Contains(type)))
            {
                return;
            }
            fsmStates[curState].Exit();
            curState = type;
            fsmStates[curState]?.Enter();
        }

        //处理所有状态，但是可以再次使用
        public void Stop()
        {
            fsmStates[curState]?.Exit();
            curState = null;

            foreach (var state in fsmStates)
                state.Value.MoonObjPushPool();

            fsmStates.Clear();
            transitionMap.Clear();
        }

        //状态彻底删除，回归对象池
        public void Destroy()
        {
            Stop();
            //放弃所有资源引用
            entity = default;
            this.MoonObjPushPool();  
        }
    }
}